// 泛型: 软件工程中，我们不仅要创建一致的定义良好的API，同时也要考虑可重用性。 组件不仅能够支持当前的数据类型，同时也能支持未来的数据类型，这在创建大型系统时为你提供了十分灵活的功能。

export function add<T>(x: T): T {
	return x
}

const a1 = add<number>(1)
const a2 = add<string>("123")
const a3 = add<number[]>([1, 2, 3])

// 类型没有通过： 类型“boolean”的参数不能赋给类型“number”的参数。
// const s4 = add<number>(true)

// 使用泛型变量
function loggingIdentity<T>(arg: T[]): T[] {
	console.log(arg.length);
	return arg;
}

loggingIdentity<number>([1, 2, 3, 4, 5])

// 泛型类型

function getId<T>(code: T): T {
	return code
}

const id: <T>(code: T) => T = getId


// 泛型类
class Person<T> {
	name: string
	age: T
	constructor(name: string, age: T) {
		this.name = name
		this.age = age
	}
}

const s = new Person<number>('张三', 18)
const s1 = new Person<string>('李四', "20")


// 泛型约束
function length<T extends { length: number }>(param: T): number {
	return param.length
}

const len = length<string>('1231231');
const l = length([1, 2, 3, 4])
const r = length({ length: 123 })

// 泛型接口
interface PersonType<T, U> {
	username: string
	password: string
	age: T
	sex: '男' | '女',
	code: U
}
const p1: PersonType<number, number> = {
	username: 'zhangsan',
	password: '123456',
	age: 18,
	sex: '男',
	code: 110
}
const p2: PersonType<number, string> = {
	username: 'zhangsan',
	password: '123456',
	age: 18,
	sex: '男',
	code: "120"
}


// 算法：要求封装一个函数  交换两个值
// swap([1,2]) => [2,1]
function swap<T, U>(arr: [T, U]): [U, T] {
	return [arr[1], arr[0]]
}

const swap1 = swap([1, 2])
const swap2 = swap([true, {}])
const swap3 = swap([new Date(), 123])

// 算法： 封装栈结构

class Stack<T> {
	list: T[] = []

	push(value: T) {
		this.list.push(value)
	}

	pop(): T | undefined {
		return this.list.pop()
	}
}

const st = new Stack<number>()

st.push(1)
st.push(2)
st.push(3)
console.log(st);
const result = st.pop()
const result1 = st.pop()
if (typeof result !== 'undefined')
	st.push(result)
console.log(result1, st)

// st.push(true)
// st.push("哈哈")


